package whf.framework.web.tag;

import java.beans.PropertyDescriptor;
import java.io.Serializable;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

import whf.framework.entity.PropertyTypeEnum;
import whf.framework.exception.AppException;
import whf.framework.ext.entity.DictItem;
import whf.framework.meta.entity.IMeta;
import whf.framework.meta.entity.IProperty;
import whf.framework.meta.service.ObjectService;
import whf.framework.meta.service.ObjectServiceImp;
import whf.framework.util.BeanUtils;
import whf.framework.util.StringUtils;
import whf.framework.web.Constants;
import whf.framework.web.tag.ext.IColumn;

/**
 * @author wanghaifeng
 *
 */
public class TableColumn implements Serializable, IColumn{
	
	private String format; // 显示格式，对于时间数字等使用

	private String property; // 显示属性，可以是表达式

	private String displayTitle; // 显示标签

	private int maxLength; // 显示最大长度，超过时被截断
	
	private int displayWidth;

	private boolean jsSort;
	
	private String headerClass;
	
	private String columnGroup;
	
	private String htmlAttributes;
	
	private String dataType;
	
	private boolean required;
	
	private String maxValue;
	
	private String minValue;
	
	private String queryString;
	
	private boolean visible = true;
	
	private String dictCategoryCode;
	
	private boolean allowMultiRows;
	
	//static text functions;
	private String hyperLink;
	
	private String jsFunction;
	
	private int visibleLevel;
	
	private int editableLevel;
	
	private int colspan;
	
	private boolean queryCondition;
	
	private boolean readonly;
	
	private IProperty propertyObject;
	/**
	 * this column will be this display type, such as select, text etc.
	 */
	private String displayType;
	
	/**
	 * 被使用为字段提示
	 */
	private String remarks;
	
	private boolean viewObjectDetail;
	
	private String promptTitle;
	
	/**
	 * 是否枚举业务对象
	 * @property boolean:enumSelections
	 */
	private boolean enumSelections;
	/**
	 * 直接输出，缺省的系统总是会经过一系列的判断最终输出值，使用这个属性值可以直接输出
	 * 可以大量的使用在tablecolumn中编程的情况
	 * @property boolean:outputDirect
	 */
	private boolean outputDirect;
	
	private String regexPattern;
	
	private String regexPatternSample;
	
	/**
	 * @return Returns the enumSelections.
	 */
	public boolean isEnumSelections() {
		return enumSelections;
	}

	/**
	 * @param enumSelections The enumSelections to set.
	 */
	public void setEnumSelections(boolean enumSelections) {
		this.enumSelections = enumSelections;
	}

	public static TableColumn loadFromMeta(Class boClass, String property) throws AppException{
		ObjectService service = ObjectServiceImp.getObjectService();
		IMeta meta = service.findByEntityClass(boClass.getName());
		if(meta != null){
			return new TableColumn(meta.findProperty(property));
		}else {
			return null;
		}
	}

	public TableColumn(IProperty prop) {
		this.propertyObject = prop;
		//
		this.maxLength = prop.getDisplayMaxLength();
		this.property = prop.getName();
		this.displayTitle = prop.getDisplayTitle();
		this.promptTitle = prop.getRemarks();
		this.dictCategoryCode = prop.getDictCategoryCode();
		this.dataType = prop.getDataType();
		if(!StringUtils.isEmpty(this.dictCategoryCode) && 
				( StringUtils.isEmpty(this.dataType) || StringUtils.equalsIgnoreCase("string", this.dataType))){
			this.dataType = DictItem.class.getName();
		}
		this.displayType = prop.getDisplayType();
		this.required = prop.isRequired();
		this.maxValue = prop.getMaxValue();
		this.minValue = prop.getMinValue();
		this.queryString = prop.getQueryString();
		this.displayWidth = prop.getDisplayWidth();
		this.colspan = prop.getColspan();
		this.allowMultiRows = prop.isAllowMultiRows();
		this.hyperLink = prop.getHyperLink();
		this.htmlAttributes = prop.getHtmlAttributes();
		this.jsFunction = prop.getJsFunction();
		this.visibleLevel = prop.getVisibleLevel();
		this.editableLevel = prop.getEditableLevel();
		this.queryCondition = prop.isQueryCondition();
		this.readonly = prop.isReadonly();
		this.remarks = prop.getRemarks();
		this.viewObjectDetail = prop.isViewObjectDetail();
		this.enumSelections = prop.isEnumSelections();
		this.regexPattern = prop.getRegexPattern();
		this.regexPatternSample = prop.getRegexPatternSample();
	}

	public TableColumn(String property) {
		this.property = property;
	}
	
	public TableColumn(PropertyDescriptor descriptor){
		this.property = descriptor.getName();
		this.displayTitle = descriptor.getDisplayName();
		this.dataType = descriptor.getPropertyType().getName();
	}
	
	public String getName(){
		return this.property;
	}

	public String getFormat() {
		return format;
	}

	public void setFormat(String format) {
		this.format = format;
	}

	public boolean isJsSort() {
		return jsSort;
	}

	public void setJsSort(boolean jsSort) {
		this.jsSort = jsSort;
	}

	public String getDisplayTitle() {
		if(!StringUtils.isEmpty(this.displayTitle)){
			return this.displayTitle;
		} else if(!StringUtils.isEmpty(this.property)){
			return this.property;
		}
		return "&nbsp;";
	}

	public void setDisplayTitle(String label) {
		this.displayTitle = label;
	}

	public int getMaxLength() {
		return maxLength;
	}

	public void setMaxLength(int length) {
		this.maxLength = length;
	}

	public String getProperty() {
		return property;
	}

	public void setProperty(String property) {
		this.property = property;
	}

	public String getHeaderClass() {
		return headerClass;
	}

	public void setHeaderClass(String headerClass) {
		this.headerClass = headerClass;
	}

	public String getColumnGroup() {
		return columnGroup;
	}

	public void setColumnGroup(String columnGroup) {
		this.columnGroup = columnGroup;
	}

	public String getHtmlAttributes() {
		if(StringUtils.isEmpty(this.htmlAttributes)){
			return "";
		} else {
			return htmlAttributes;
		}
	}

	public void setHtmlAttributes(String htmlAttributes) {
		this.htmlAttributes = htmlAttributes;
	}

	public String getDataType() {
		return dataType;
	}

	public void setDataType(String dataType) {
		this.dataType = dataType;
	}

	public String getDisplayType() {
		return displayType;
	}

	public void setDisplayType(String displayType) {
		this.displayType = displayType;
	}

	public String getMaxValue() {
		return maxValue;
	}

	public void setMaxValue(String maxValue) {
		this.maxValue = maxValue;
	}

	public String getMinValue() {
		return minValue;
	}

	public void setMinValue(String minValue) {
		this.minValue = minValue;
	}

	public boolean isRequired() {
		return required;
	}

	public void setRequired(boolean required) {
		this.required = required;
	}

	public String getQueryString() {
		return queryString;
	}

	public void setQueryString(String queryString) {
		this.queryString = queryString;
	}

	public int getDisplayWidth() {
		if(this.displayWidth <= 0){
			return Constants.DEFAULT_DISPLAY_WIDTH;
		}
		return displayWidth;
	}

	public void setDisplayWidth(int displayWidth) {
		this.displayWidth = displayWidth;
	}

	public boolean isVisible() {
		return visible;
	}

	public void setVisible(boolean visible) {
		this.visible = visible;
	}

	public boolean isAllowMultiRows() {
		return allowMultiRows;
	}

	public void setAllowMultiRows(boolean allowMultiRows) {
		this.allowMultiRows = allowMultiRows;
	}

	public int getColspan() {
		return colspan;
	}

	public void setColspan(int colspan) {
		this.colspan = colspan;
	}

	public String getDictCategoryCode() {
		return dictCategoryCode;
	}

	public void setDictCategoryCode(String dictCategoryCode) {
		this.dictCategoryCode = dictCategoryCode;
	}

	public String getHyperLink() {
		return hyperLink;
	}

	public void setHyperLink(String hyperLink) {
		this.hyperLink = hyperLink;
	}

	public String getJsFunction() {
		return jsFunction;
	}

	public void setJsFunction(String jsFunction) {
		this.jsFunction = jsFunction;
	}

	public int getVisibleLevel() {
		return visibleLevel;
	}

	public void setVisibleLevel(int visibleLevel) {
		this.visibleLevel = visibleLevel;
	}

	public int getEditableLevel() {
		return editableLevel;
	}

	public void setEditableLevel(int editableLevel) {
		this.editableLevel = editableLevel;
	}

	public boolean isQueryCondition() {
		return queryCondition;
	}

	public void setQueryCondition(boolean queryCondition) {
		this.queryCondition = queryCondition;
	}

	public IProperty getPropertyObject() {
		return propertyObject;
	}

	public boolean isReadonly() {
		return readonly;
	}

	public void setReadonly(boolean readonly) {
		this.readonly = readonly;
	}

	public String getRemarks() {
		return remarks;
	}

	public void setRemarks(String remarks) {
		this.remarks = remarks;
	}

	public boolean isViewObjectDetail() {
		return viewObjectDetail;
	}

	public void setViewObjectDetail(boolean viewObjectDetail) {
		this.viewObjectDetail = viewObjectDetail;
	}

	public String getPromptTitle() {
		if(StringUtils.isEmpty(this.promptTitle)){
			this.promptTitle = this.remarks;
			if(StringUtils.isEmpty(this.promptTitle)){
				this.promptTitle = this.displayTitle;
			}
		}
		return promptTitle;
	}
	
	/**
	 * @return Returns the outputDirect.
	 */
	public final boolean isOutputDirect() {
		return outputDirect;
	}

	/**
	 * @param outputDirect The outputDirect to set.
	 */
	public final void setOutputDirect(boolean outputDirect) {
		this.outputDirect = outputDirect;
	}
	
	public PropertyTypeEnum getPropType(Object propertyValue){
		return BeanUtils.getPropertyType(propertyValue, this.propertyObject);
	}
	
	public boolean isImageType(){
		return this.displayType == null? false: this.displayType.toLowerCase().indexOf("image") >= 0;
	}

	public String toString(){
		return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
	}

	/**
	 * @return Returns the regexPattern.
	 */
	public String getRegexPattern() {
		return regexPattern;
	}

	/**
	 * @param regexPattern The regexPattern to set.
	 */
	public void setRegexPattern(String regexPattern) {
		this.regexPattern = regexPattern;
	}

	/**
	 * @return Returns the regexPatternSample.
	 */
	public String getRegexPatternSample() {
		return regexPatternSample;
	}

	/**
	 * @param regexPatternSample The regexPatternSample to set.
	 */
	public void setRegexPatternSample(String regexPatternSample) {
		this.regexPatternSample = regexPatternSample;
	}
}
